#ifndef LISTWIDGET_H
#define LISTWIDGET_H

#include <string>
#include <list>
#include <vector>

class ListWidgetItem
{
public:
	ListWidgetItem(std::string text = "", hgeSprite* sprite = 0)
	{
		mText = text;
		mSprite = sprite;
	}
	virtual ~ListWidgetItem()
	{
	}
	std::string GetText()
	{
		return mText;
	}
	void SetText(std::string value)
	{
		mText = value;
	}
	hgeSprite* GetSprite()
	{
		return mSprite;
	}
	void SetSprite(hgeSprite* value)
	{
		mSprite = value;
	}
	void Render(float x, float y, float w, float h)
	{
		if (mSprite)
			mSprite->Render4V(x, y, x+w, y, x + w, y + h, x, y + h);
		mFont->printf((x+x+w)/ 2.0, y + h / 4, HGETEXT_CENTER, mText.data());
	}
	void Update(float dt)
	{
	}
	hgeFont* GetFont()
	{
		return mFont;
	}
	void SetFont(hgeFont* font)
	{
		mFont = font;
	}
protected:
	std::string mText;
	hgeSprite* mSprite;
	hgeFont* mFont;
};

typedef std::vector<ListWidgetItem*> ItemList;

class ListWidget : public GUIObject
{
public:
	ListWidget(float x, float y, float w, float h, hgeFont *fnt)
	{
		this->id = (DWORD)this;
		bStatic=false;
		bVisible=true;
		bEnabled=true;
		rect.Set(x, y, x+w, y+h);
		mX = 0;
		mY = 0;
		mTopItem = 0;
		SetSelectedItem(-1);
		SetRowSize(20.0f);

		sprHighlight = new hgeSprite(0, 0, 0, w, mRowSize);
		sprHighlight->SetColor(ARGB(0xff, 0x77, 0x77, 0x77));

		mSheetSprite = new hgeSprite(0, 0, 0, w, h);
		mSheetSprite->SetColor(ARGB(0xff, 0x50, 0x77, 0xf0));
	}

	virtual	~ListWidget()
	{
		Clear();
		if(sprHighlight) delete sprHighlight;
	}

	int	AddItem(ListWidgetItem *item)
	{
		mItems.push_back(item);
		return mItems.size() - 1;
	}
	void DeleteItem(int n)
	{
		ItemList::iterator it = mItems.begin();
		for (int i = 0; i < n; ++i)
			++it;
		mItems.erase(it);
	}
	int	GetSelectedNumber() 
	{ 
		return mSelectedNumber; 
	}
	ListWidgetItem* GetSelectedItem() 
	{
		return mItems.at(mSelectedNumber);
	}
	void SetSelectedItem(int n) 
	{ 
		if(n >= 0 && n < GetCount()) 
		{
			mSelectedNumber = n; 
			mCurrent = mItems.begin();
			for (int i = 0; i < n; ++i)
				++mCurrent;
		}
	}
	int GetCount()
	{
		return mItems.size();
	}
	int	GetTopItem() 
	{ 
		return mTopItem; 
	}
	void SetRowSize(float height)
	{
		mRowSize = height;
		mVisibleCount = (int)((rect.y2 - rect.y1) / mRowSize);
	}
	void SetTopItem(int n) 
	{ 
		if(n>=0 && n <= GetBottomNumber()) 
			mTopItem = n; 
	}

	void			Clear()
	{
		for (ItemList::iterator it = mItems.begin(); it != mItems.end(); ++it)
			delete *it;

		mSelectedNumber = -1;
		mItems.clear();
		mCurrent = mItems.end();
		mTopItem = -1;
	}

	virtual void	Render()
	{
		int count = mItems.size();
		int lastViewSize = count % mVisibleCount == 0 ? mVisibleCount : count % mVisibleCount;
		maxTopItem = count - lastViewSize;

		mSheetSprite->Render4V(rect.x1, rect.y1, rect.x2, rect.y1, rect.x2, rect.y2, rect.x1, rect.y2);
		int selectedY = GetSelectedNumber() - mTopItem;
		if (selectedY >= 0 && selectedY < mVisibleCount)
			sprHighlight->Render(rect.x1 + 4, selectedY * mRowSize + rect.y1);
		
		int i = 0;
		ItemList::iterator it = mItems.begin();
		for (int i = 0; i < mTopItem; ++i)
			++it;

		for (i = 0; i < mVisibleCount && it != mItems.end(); ++i)
		{
			(*it)->Render(rect.x1 + 4, rect.y1 + mRowSize * i, rect.x2 - rect.x1, mRowSize);
			++it;
		}
	}
	virtual bool	MouseMove(float x, float y) 
	{ 
		mX=x; 
		mY=y; 
		return false; 
	}
	virtual bool	MouseLButton(bool bDown)
	{
		int nItem;

		if(bDown)
		{
			nItem=GetTopItem()+int(mY)/int(mRowSize);
			if(nItem<GetCount())
			{
				SetSelectedItem(nItem);
				return true;
			}
		}

		return false;
	}
	virtual bool	MouseWheel(int nNotches)
	{
		return false;
	}
	virtual bool	KeyClick(int key, int chr)
	{
		return false;
	}
	int GetBottomNumber()
	{
		return min(mVisibleCount + mTopItem, mItems.size());
	}
	void SetSheetSprite(hgeSprite* sprite)
	{
		mSheetSprite = sprite;
	}
	void SetHighlightSprite(hgeSprite* sprite)
	{
		sprHighlight = sprite;
	}
	void Scroll(int shift = 1)
	{
		SetTopItem(mTopItem + shift);
	}
	void Scroll(float ratio)
	{
		if (ratio < 0.0f) ratio = 0.0f;
		if (ratio > 1.0f) ratio = 1.0f;

		int count = mItems.size();
		int lastViewSize = count % mVisibleCount == 0 ? mVisibleCount : count % mVisibleCount;
		maxTopItem = count - lastViewSize;
		mTopItem = ratio * maxTopItem;
	}
private:
	hgeSprite		*sprHighlight;
	hgeSprite* mSheetSprite;
	hgeFont			*font;
	DWORD			textColor, texthilColor;

	float				mX, mY;
	ItemList mItems;
	ItemList::iterator mCurrent;
	float mRowSize;
	int mSelectedNumber;
	int mTopItem;
	int mVisibleCount;

	int maxTopItem;
};

#endif